import pywt
import numpy as np
import logging
from service.DeltaService import DeltaService
import sys
import os

# 添加项目根目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(current_dir)
if project_root not in sys.path:
    sys.path.append(project_root)

from response.BrainWaveResult import BrainWaveResult
from exception.base_exceptions import SignalProcessingException, DeviceConnectionException
from exception.exception_handler import global_exception_handler

# 设置日志
logger = logging.getLogger(__name__)

class WaveletDeltaService(DeltaService):
    """基于小波包分解的Delta波段分析服务"""
    
    def __init__(self, port=None, analysis_duration=10):
        super().__init__(port, analysis_duration=analysis_duration)
        self.wavelet_type = 'db4'  # 默认小波基
        self.decomposition_level = 5  # 分解层数
        self.__wavelet_filtered_delta = 0.0  # 存储小波包分析后的delta值
        self.__original_delta = 0  # 初始化原始delta属性
    
    @property
    def delta(self):
        """获取原始delta值"""
        return self._DeltaService__original_delta
    
    @delta.setter
    def delta(self, value):
        """设置delta值时自动进行小波包分析"""
        try:
            # 先设置父类的原始delta值
            self._DeltaService__original_delta = value
            logger.debug(f"WaveletDeltaService: 接收到新的delta值: {value}")
            
            # 使用小波包分析计算过滤后的delta值
            # 获取分离的Delta频段功率
            low_delta_power, high_delta_power = self._perform_wavelet_analysis()
            # 使用高频Delta (2-4Hz) 作为过滤后的delta值
            self.__wavelet_filtered_delta = high_delta_power
            logger.debug(f"Delta设置: 原始={value}, 低频Delta={low_delta_power}, 高频Delta={high_delta_power}")
            
            # 如果小波分析失败，使用简单的比例估算
            if high_delta_power == 0 and value > 0:
                # 估算高频Delta约占总Delta的30-40%
                estimated_filtered = int(value * 0.35)
                self.__wavelet_filtered_delta = estimated_filtered
                logger.debug(f"小波分析失败，使用估算值: {estimated_filtered}")
                
        except Exception as e:
            processing_error = SignalProcessingException(
                f"小波包分析失败: {str(e)}",
                signal_type="wavelet_delta_analysis"
            )
            global_exception_handler.handle_exception(processing_error)
            # 如果分析失败且原始值大于0，使用估算值
            if value > 0:
                estimated_filtered = int(value * 0.35)
                self.__wavelet_filtered_delta = estimated_filtered
                logger.debug(f"异常处理，使用估算值: {estimated_filtered}")
            else:
                self.__wavelet_filtered_delta = 0.0
        
        # 注意：不调用父类的delta setter，因为我们已经手动设置了原始delta值
        # 并且我们使用自己的小波分析逻辑来计算过滤后的值
    
    @property
    def filtered_delta(self):
        """获取小波包过滤后的delta值（2-4Hz）"""
        return self.__wavelet_filtered_delta
    
    @filtered_delta.setter
    def filtered_delta(self, value):
        """直接设置小波包过滤后的delta值"""
        self.__wavelet_filtered_delta = value
    
    def get_filtered_delta(self):
        """
        重写父类方法，返回小波包过滤后的delta值
        这个方法在数据收集时被调用
        """
        return self.__wavelet_filtered_delta
    
    def _calculate_microvolts(self, filtered_adc):
        """
        从ADC值到μV的完整转换流程
        
        Args:
            filtered_adc: 过滤后的ADC值
            
        Returns:
            float: 微伏特值
        """
        try:
            # 步骤1: ADC转电压 (TGAM1芯片规格)
            raw_voltage = (filtered_adc / 32768) * 200  # ±32768对应±200μV
            
            # 步骤2: 应用基线补偿
            compensated = raw_voltage + 15  # 硬件基线偏移
            
            # 步骤3: 功率转振幅换算 (EEG信号特性)
            amplitude = compensated * 0.707  # RMS值转换
            
            # 步骤4: 带通滤波修正系数
            bandpass_factor = 0.8  # 2-4Hz带宽补偿
            
            return amplitude * bandpass_factor
        except Exception as e:
            processing_error = SignalProcessingException(
                f"微伏计算内部错误: {str(e)}",
                signal_type="microvolt_calculation"
            )
            global_exception_handler.handle_exception(processing_error)
            return 0.0

    def wavelet_denoise(self, signal):
        # 检查输入信号有效性
        if len(signal) < 512:
            return signal
            
        # 小波分解
        coeffs = pywt.wavedec(signal, self.wavelet_type, level=self.decomposition_level)
        
        # 自适应阈值计算
        sigma = np.median(np.abs(coeffs[-1])) / 0.6745
        threshold = sigma * np.sqrt(2 * np.log(len(signal)))
        
        # 分层阈值处理
        coeffs_thresh = []
        for i, c in enumerate(coeffs):
            if i < len(coeffs)-1:  # 高频系数
                coeffs_thresh.append(pywt.threshold(c, threshold, mode='soft'))
            else:  # 低频系数
                coeffs_thresh.append(c)
        
        # 信号重构
        denoised = pywt.waverec(coeffs_thresh, self.wavelet_type)
        
        # 长度对齐
        return denoised[:len(signal)]
    
    def _perform_wavelet_analysis(self):
        """
        使用小波包进行Delta频段分析
        
        Returns:
            tuple: (low_delta_power, high_delta_power) 低频和高频Delta功率
        """
        try:
            # 获取缓冲区中的信号数据
            buffer_size = len(self._DeltaService__raw_signal_buffer)
            # 动态计算最小缓冲区大小（基于分析时长）
            min_buffer_size = int(self._DeltaService__sampling_rate * self.analysis_duration)
            if buffer_size < min_buffer_size:
                logger.debug(f"小波分析跳过: 缓冲区样本不足 ({buffer_size}/{min_buffer_size})")
                return 0.0, 0.0
            
            logger.debug(f"开始小波分析，缓冲区大小: {buffer_size}")
            
            signal_data = np.array(list(self._DeltaService__raw_signal_buffer))
            logger.debug(f"信号数据范围: [{np.min(signal_data):.2f}, {np.max(signal_data):.2f}], 均值: {np.mean(signal_data):.2f}")
            
            # 检查信号是否全为0或常数
            if np.std(signal_data) == 0:
                logger.warning("信号数据为常数，无法进行频谱分析")
                return 0.0, 0.0
            
            # 去除直流分量
            signal_data = signal_data - np.mean(signal_data)
            logger.debug(f"去除直流后范围: [{np.min(signal_data):.2f}, {np.max(signal_data):.2f}], 标准差: {np.std(signal_data):.2f}")
            
            # 简化版本：先不使用小波去噪，直接计算功率
            # 应用小波去噪
            signal_data = self.wavelet_denoise(signal_data)
            logger.debug(f"去噪后信号范围: [{np.min(signal_data):.2f}, {np.max(signal_data):.2f}], 标准差: {np.std(signal_data):.2f}")
            
            # 简化版本：不使用汉宁窗
            logger.debug("跳过汉宁窗处理")
            
            # 直接计算Delta频段功率（使用简单的FFT方法）
            logger.debug(f"采样率: {self._DeltaService__sampling_rate}")
            
            # 方法1: 使用带通滤波器真正过滤信号
            # 过滤出完整的Delta频段 (0.5-4Hz)
            delta_signal = self._bandpass_filter(signal_data, 0.5, 4.0, self._DeltaService__sampling_rate)
            
            # 过滤出低频部分 (0.5-2Hz)
            low_freq_signal = self._bandpass_filter(signal_data, 0.5, 2.0, self._DeltaService__sampling_rate)
            
            # 直接过滤出高频部分 (2-4Hz) - 这才是正确的做法
            filtered_signal = self._bandpass_filter(signal_data, 2.0, 4.0, self._DeltaService__sampling_rate)
            
            # 计算各频段功率
            delta_power = np.mean(delta_signal ** 2)
            low_freq_power = np.mean(low_freq_signal ** 2)
            filtered_power = np.mean(filtered_signal ** 2)
            
            logger.debug(f"信号功率分析:")
            logger.debug(f"  原始Delta(0.5-4Hz)功率: {delta_power:.6f}")
            logger.debug(f"  低频(0.5-2Hz)功率: {low_freq_power:.6f}")
            logger.debug(f"  过滤后(2-4Hz)功率: {filtered_power:.6f}")
            
            # 方法2: 同时使用FFT验证
            fft_data = np.fft.fft(signal_data)
            freqs = np.fft.fftfreq(len(signal_data), 1/self._DeltaService__sampling_rate)
            power_spectrum = np.abs(fft_data) ** 2
            
            # 找到Delta频段的索引
            delta_mask = (np.abs(freqs) >= 0.5) & (np.abs(freqs) <= 4.0)
            low_delta_mask = (np.abs(freqs) >= 0.5) & (np.abs(freqs) <= 2.0)
            high_delta_mask = (np.abs(freqs) >= 2.0) & (np.abs(freqs) <= 4.0)
            
            # 计算FFT功率谱中的各频段功率（用于验证）
            fft_total_delta = np.mean(power_spectrum[delta_mask]) if np.sum(delta_mask) > 0 else 0.0
            fft_low_delta = np.mean(power_spectrum[low_delta_mask]) if np.sum(low_delta_mask) > 0 else 0.0
            fft_high_delta = np.mean(power_spectrum[high_delta_mask]) if np.sum(high_delta_mask) > 0 else 0.0
            
            logger.debug(f"FFT验证 - 总Delta: {fft_total_delta:.6f}, 低频: {fft_low_delta:.6f}, 高频: {fft_high_delta:.6f}")
            
            # 使用时域滤波结果作为主要输出
            low_delta_power = low_freq_power
            high_delta_power = filtered_power
            total_delta_power = delta_power
            
            logger.debug(f"功率分析 - 总Delta: {total_delta_power:.6f}, 低频: {low_delta_power:.6f}, 高频: {high_delta_power:.6f}")
            
            # 获取当前原始delta值作为基准
            current_original_delta = self._DeltaService__original_delta if hasattr(self, '_DeltaService__original_delta') else 1000
            logger.debug(f"当前原始Delta基准值: {current_original_delta}")
            
            # 计算频段比例并转换为微伏特单位
            high_freq_ratio = 0.0
            low_freq_ratio = 0.0
            scaled_high = 0
            scaled_low = 0
            
            if total_delta_power > 0:
                high_freq_ratio = high_delta_power / total_delta_power
                low_freq_ratio = low_delta_power / total_delta_power
                
                # ADC到微伏特的转换因子 (基于NeuroSky TGAM1芯片规格)
                # TGAM1的ADC范围是±32768，对应±200μV
                adc_to_uv_factor = 200.0 / 32768.0  # 约0.0061μV/ADC
                
                # 将功率转换为微伏特
                # 功率的平方根近似为信号幅度
                delta_amplitude_uv = np.sqrt(total_delta_power) * adc_to_uv_factor
                high_amplitude_uv = np.sqrt(high_delta_power) * adc_to_uv_factor
                low_amplitude_uv = np.sqrt(low_delta_power) * adc_to_uv_factor
                
                # 为了保持与原有系统的兼容性，将微伏特值放大到合适的显示范围
                # 正常Delta波在20-50μV，工作状态应该更低
                display_scale_factor = 100  # 放大100倍用于显示
                
                scaled_high = int(high_amplitude_uv * display_scale_factor)
                scaled_low = int(low_amplitude_uv * display_scale_factor)
                
                # 确保不为负数
                scaled_high = max(scaled_high, 0)
                scaled_low = max(scaled_low, 0)
                
                logger.debug(f"功率转换 - 总Delta幅度: {delta_amplitude_uv:.2f}μV, 高频: {high_amplitude_uv:.2f}μV, 低频: {low_amplitude_uv:.2f}μV")
                logger.debug(f"显示值 - 低频: {scaled_low}, 高频: {scaled_high}")
                
                # 工作状态判断
                if high_amplitude_uv < 30:
                    logger.info(f"✅ 工作状态良好 - Delta(2-4Hz): {high_amplitude_uv:.1f}μV (正常范围: <30μV)")
                elif high_amplitude_uv < 50:
                    logger.warning(f"⚠️  轻度疲劳 - Delta(2-4Hz): {high_amplitude_uv:.1f}μV (建议休息)")
                else:
                    logger.warning(f"❌ 疲劳状态 - Delta(2-4Hz): {high_amplitude_uv:.1f}μV (需要休息)")
            else:
                logger.debug("总Delta功率为0，返回0值")
            
            return scaled_low, scaled_high
            
        except Exception as e:
            processing_error = SignalProcessingException(
                f"小波分析过程中出错: {str(e)}",
                signal_type="wavelet_analysis"
            )
            global_exception_handler.handle_exception(processing_error)
            return 0.0, 0.0
    
    def _bandpass_filter(self, signal, low_freq, high_freq, sampling_rate):
        """
        简单的带通滤波器实现
        
        Args:
            signal: 输入信号
            low_freq: 低频截止频率
            high_freq: 高频截止频率
            sampling_rate: 采样率
            
        Returns:
            filtered_signal: 滤波后的信号
        """
        # 使用FFT实现简单的带通滤波
        fft_data = np.fft.fft(signal)
        freqs = np.fft.fftfreq(len(signal), 1/sampling_rate)
        
        # 创建带通滤波器掩码
        mask = (np.abs(freqs) >= low_freq) & (np.abs(freqs) <= high_freq)
        
        # 应用滤波器
        fft_data[~mask] = 0
        
        # 逆变换得到滤波后的信号
        filtered_signal = np.real(np.fft.ifft(fft_data))
        
        return filtered_signal
    
    def _scale_power(self, power):
        """
        缩放功率值以匹配原有范围
        
        Args:
            power: 原始功率值
            
        Returns:
            scaled_power: 缩放后的功率值
        """
        # 将功率转换为与EEG设备输出相似的数值范围
        # 使用对数缩放来压缩大的功率值
        if power > 0:
            # 使用对数变换来获得更合理的数值范围
            scaled_power = int(np.log10(power + 1) * 1000)
            # 确保在合理范围内 (几百到几万)
            scaled_power = min(max(scaled_power, 100), 50000)
        else:
            scaled_power = 0
            
        return scaled_power
    
    def process_delta(self, data_dict):
        """
        处理Delta频段数据
        
        Args:
            data_dict: 包含原始脑电数据的字典
            
        Returns:
            dict: 处理后的数据字典
        """
        try:
            # 获取原始delta值
            original_delta = data_dict.get('delta', 0)
            
            # 设置delta值，这会触发小波包分析
            self.delta = original_delta
            
            # 获取小波包过滤后的delta值
            filtered_delta = self.filtered_delta
            
            # 更新数据字典
            data_dict['delta'] = filtered_delta
            data_dict['original_delta'] = original_delta
            
            return data_dict
        except Exception as e:
            exception = SignalProcessingException(f"小波Delta处理失败，处理类型: process_delta，错误详情: {str(e)}")
            global_exception_handler.handle_exception(exception)
            # 保持原始值不变
            return data_dict
            
    def process_delta_result(self, result):
        """
        处理Delta频段数据，接收并返回BrainWaveResult对象
        
        Args:
            result: BrainWaveResult对象
            
        Returns:
            BrainWaveResult: 处理后的BrainWaveResult对象
        """
        try:
            # 获取原始delta值
            original_delta = result.delta
            
            # 设置delta值，这会触发小波包分析
            self.delta = original_delta
            
            # 获取小波包过滤后的delta值
            filtered_delta = self.filtered_delta
            
            # 更新BrainWaveResult对象
            result.original_delta = original_delta
            result.delta = filtered_delta
            
            # 添加处理步骤信息
            result.add_processing_step(
                "wavelet_delta_filter", 
                {
                    "original_delta": original_delta,
                    "filtered_delta": filtered_delta,
                    "filter_type": "wavelet",
                    "wavelet_type": self.wavelet_type,
                    "decomposition_level": self.decomposition_level
                }
            )
            
            return result
        except Exception as e:
            exception = SignalProcessingException(f"小波Delta结果处理失败，处理类型: process_delta_result，错误详情: {str(e)}")
            global_exception_handler.handle_exception(exception)
            # 保持原始值不变
            return result
    
    def get_separated_delta_bands(self):
        """
        获取分离的Delta频段功率
        重写父类方法，使用小波包分析替代FFT分析
        
        Returns:
            tuple: (low_delta_power, high_delta_power)
        """
        return self._perform_wavelet_analysis()
    
    def _output_collected_data(self):
        """
        重写父类方法，添加小波分析特定的缓冲区状态信息
        """
        if not self._DeltaService__data_collection_buffer:
            return
            
        # 获取缓冲区状态信息
        buffer_size = len(self._DeltaService__raw_signal_buffer)
        buffer_percentage = (buffer_size / 5120) * 100
        wavelet_ready = "✅" if buffer_size >= 5120 else "❌"
        fft_ready = "✅" if buffer_size >= 512 else "❌"
        
        # print(f"\n=== 10秒数据收集完成，共{len(self._DeltaService__data_collection_buffer)}个样本 ===")  # 删除数据收集打印
        # print(f"rawValue缓冲区状态: {buffer_size}/5120 样本 ({buffer_percentage:.1f}%)")
        # print(f"小波分析就绪: {wavelet_ready} (需要≥5120样本)")
        # print(f"FFT分析就绪: {fft_ready} (需要≥512样本)")
        # print("时间戳 | 原始Delta(0.5-4Hz) | 过滤Delta(2-4Hz) | Raw | Theta | Alpha | Beta | Gamma | 注意力 | 冥想度 | 信号")
        print("-" * 120)
        
        for i, sample in enumerate(self._DeltaService__data_collection_buffer):
            timestamp = sample['timestamp'] - self._DeltaService__collection_start_time  # 相对时间
            # print(f"{timestamp:6.1f}s | {int(sample['original_delta']):8d} | {int(sample['filtered_delta']):8d} | "
            #       f"{sample['raw_value']:4d} | {sample['theta']:5d} | {sample['alpha']:5d} | "
            #       f"{sample['beta']:4d} | {sample['gamma']:5d} | {sample['attention']:3d} | "
            #       f"{sample['meditation']:3d} | {sample['signal']:2d}")  # 删除样本详情打印
            pass
        
        # 计算统计信息
        original_deltas = [s['original_delta'] for s in self._DeltaService__data_collection_buffer]
        filtered_deltas = [s['filtered_delta'] for s in self._DeltaService__data_collection_buffer]
        
        print("-" * 120)
        # print(f"原始Delta统计: 平均={np.mean(original_deltas):.0f}, 最大={max(original_deltas)}, 最小={min(original_deltas)}")
        # print(f"过滤Delta统计: 平均={np.mean(filtered_deltas):.0f}, 最大={max(filtered_deltas)}, 最小={min(filtered_deltas)}")  # 删除统计打印
        
        # 分析过滤效果
        if np.mean(original_deltas) > 0:
            filter_reduction = (1 - np.mean(filtered_deltas)/np.mean(original_deltas))*100
            # print(f"小波过滤效果: 平均降低了{filter_reduction:.1f}%")  # 删除过滤效果打印
        else:
            # print(f"小波过滤效果: 原始Delta为0，无法计算")  # 删除过滤效果打印
            pass
            
        # 分析过滤失败的原因（小波分析特定）
        zero_filtered_count = sum(1 for d in filtered_deltas if d == 0)
        if zero_filtered_count > 0:
            # print(f"⚠️  小波过滤失败样本: {zero_filtered_count}/{len(filtered_deltas)} ({zero_filtered_count/len(filtered_deltas)*100:.1f}%)")  # 删除失败样本打印
            if buffer_size < 5120:
                # print(f"   原因: rawValue缓冲区数据不足，小波分析需要5120样本 ({buffer_size}/5120)")  # 删除原因打印
                pass
            else:
                # print(f"   原因: 可能是信号质量问题或小波分析参数需要调整")  # 删除原因打印
                pass
        
        print("=" * 120)


# 使用示例
if __name__ == "__main__":
    import time
    
    # 小波包DeltaService测试程序
    print("=" * 50)
    
    # 创建WaveletDeltaService实例
    wavelet_delta_service = WaveletDeltaService("COM5")
    
    try:
        # 启动设备
        print("正在启动设备...")
        wavelet_delta_service.start()
        print("设备启动成功")
        
        # 等待设备稳定
        print("等待设备信号稳定...")
        time.sleep(3)
        
        # 连续获取数据
        i = 1
        while True:
            print(f"\n--- 第 {i} 次数据采集 ---")
            
            # 打印delta状态
            wavelet_delta_service.print_delta_status()
            
            # 获取小波包分离的Delta频段数据
            low_delta_wpd, high_delta_wpd = wavelet_delta_service.get_separated_delta_bands()
            logger.debug(f"小波包分析结果:")
            logger.debug(f"  0.5-2Hz频段功率: {low_delta_wpd}")
            logger.debug(f"  2-4Hz频段功率: {high_delta_wpd}")
            
            time.sleep(1)
            i += 1
            
    except KeyboardInterrupt:
        print("\n用户中断，正在停止...")
    except Exception as e:
        device_error = DeviceConnectionException(
            f"WaveletDeltaService运行错误: {str(e)}",
            port="COM5"
        )
        global_exception_handler.handle_exception(device_error)
    finally:
        # 停止设备
        wavelet_delta_service.stop()
        print("设备已停止")